﻿import { _decorator, Component, Node, __private } from 'cc';
import { DestroyCB } from '../common/DestroyCB';
import { Functor } from '../common/Functor';
const { ccclass, property } = _decorator;

@ccclass('PropBase')
export class PropBase extends Component {
    funcMap = new Map<string, Map<any, Array<string>>>();
    static propName = "_myProp";
    watch(key: string, obj: any, funcName: string) {
        if (!this.funcMap.has(key)) {
            this.funcMap.set(key, new Map<any, Array<string>>());
        }
        let map = this.funcMap.get(key);
        if (!map.has(obj)) {
            map.set(obj, new Array<string>());
        }
        let arr = map.get(obj);
        arr.push(funcName);

        //添加自动移除需要的数据
        if (obj[PropBase.propName] == null) {
            obj[PropBase.propName] = new Set<PropBase>();
        }
        obj[PropBase.propName].add(this);
        DestroyCB.addCb(obj, this, "onObjDestroy");
    }

    async watchRun(key: string, obj: any, funcName: string) {
        this.watch(key, obj, funcName);
        await obj[funcName](this);
    }

    onObjDestroy(watchDestroyObj: any) {
        let propSet = watchDestroyObj[PropBase.propName];
        for (let prop of propSet) {
            prop.removeWatch(watchDestroyObj);
        }
    }

    async setData(data) {
        if (data == null)
            return;
        let keyArr = new Array<string>();
        for (const key in data) {
            let value = data[key]
            if (this[key] == value)
                continue;
            this[key] = value;
            keyArr.push(key);
        };
        for (let key of keyArr) {
            await this.runCb(key);
        }
    }

    removeWatch(obj: any) {
        this.funcMap.forEach((map, key) => {
            if (map != null) {
                if (map.has(obj)) {
                    map.delete(obj);
                }
            }
        })
    }

    async setValue(key: string, value: any) {
        if (this[key] == value)
            return;
        this[key] = value;
        await this.runCb(key);
    }


    async runCb(key: string) {
        if (!this.funcMap.has(key)) {
            return;
        }
        let map = this.funcMap.get(key);
        for (let obj of map.keys()) {
            let arr = map.get(obj)
            if (arr != null)
                for (let funcName of arr) {
                    await obj[funcName](this);
                }
        }



    }
}

